{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([\n",
    "    [5, 3],  # 用户1对两部电影的评分\n",
    "    [3, 5],  # 用户2对两部电影的评分\n",
    "    [2, 4],  # 用户3对两部电影的评分\n",
    "    [4, 2]   # 用户4对两部电影的评分\n",
    "])#TODO\n",
    "\n",
    "y = np.array([0, 1, 0, 1])#TODO  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=3)\n",
    "#TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\86187\\Anaconda3\\lib\\site-packages\\sklearn\\neighbors\\base.py:907: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.\n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  self._y = np.empty(y.shape, dtype=np.int)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=None, n_neighbors=3, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)# TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\86187\\Anaconda3\\lib\\site-packages\\sklearn\\metrics\\pairwise.py:54: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  dtype = np.float\n"
     ]
    }
   ],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)#TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\86187\\Anaconda3\\lib\\site-packages\\sklearn\\metrics\\pairwise.py:54: DeprecationWarning: `np.float` is a deprecated alias for the builtin `float`. To silence this warning, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.\n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  dtype = np.float\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired, edgecolor='k', s=40)#TODO\n",
    "\n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "plt.scatter(new_user[0, 0], new_user[0, 1], color='red', marker='x', s=100)#TODO\n",
    "\n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)#TODO\n",
    "nearest = X[idx[0][0]]#TODO # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "plt.plot([new_user[0, 0], nearest[0]], [new_user[0, 1], nearest[1]], 'r--')#TODO\n",
    "\n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):\n",
    "    plt.text(x, y+0.1, f'({x}, {y})') \n",
    "\n",
    "# 为新数据点添加坐标文本\n",
    "plt.text(new_user[0,0], new_user[0,1]+0.1, f'({new_user[0,0]}, {new_user[0,1]})')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
